use crate::config::app_error::AppResult;
use crate::extension::index::index::index_entry_container::IndexEntryContainer;
use crate::extension::index::index::query::index_attribute::IndexAttribute;
use crate::extension::index::index::query::index_descriptor::IndexDescriptor;
use crate::extension::index::index::query::index_entry::{IndexEntry, IndexEntryImpl};
use crate::extension::index::index::query::index_spec;
use halo_model::{ExtensionOperator, GVK};
use std::borrow::Borrow;
use std::cell::RefCell;
use std::hash::Hash;
use std::sync::Arc;
pub struct IndexBuilder {
    index_entries: IndexEntryContainer,
}

impl IndexBuilder {
    pub fn new<T: ExtensionOperator + GVK>(
        index_descriptor: Vec<IndexDescriptor<T>>,
        extension: Vec<T>,
    ) -> AppResult<Self> {
        let mut index_entries = IndexEntryContainer::new();
        for mut x in index_descriptor {
            let vec = (&extension)
                .iter()
                .map(|e| {
                    let func = &x.spec.index_func;
                    let index_keys = func.get_values(e);
                    return (
                        Vec::from_iter(index_keys),
                        index_spec::get_object_primary_key(e),
                    );
                })
                .collect::<Vec<(Vec<String>, String)>>();

            let mut index_entry = IndexEntryImpl::new(x);
            for (index_keys, object_key) in vec {
                index_entry.add_entry(index_keys, object_key)?;
            }
            let index_entry = Arc::new(RefCell::new(index_entry));

            index_entries.add(index_entry)?;
        }

        Ok(IndexBuilder { index_entries })
    }

    pub fn get_index_entries<IE: IndexEntry>(self) -> AppResult<IndexEntryContainer> {
        let vec = self.index_entries.iter::<IE>()?;
        for mut it in vec {
             // let a = it.borrow();
            let ready = it.get_mut().get_index_descriptor().ready;
            if !ready {
                return Err(anyhow::anyhow!(
                    "IndexEntry are not ready yet for index named {}",
                    it.borrow().get_index_descriptor().spec.name
                )
                .into());
            }
        }
        Ok(self.index_entries)
    }
}
